#include <ddk.h>
#include <stdlib.h>
#include <CommuChannel.h>
#include "serialTrans.h"
#include "pipeTrans.h"
#include "usbTrans.h"

#define USE_SERIAL 0
#define USE_PIPE   1
#define USE_USB    2

typedef struct tag_physi_funcs {
    int (*port_init)();
    int (*receive_data)(void *, int, int*);
    int (*send_data)(void*, int, int*);
} physi_funcs;

physi_funcs physi_calls;

int ChannelInitPort()
{
    return physi_calls.port_init();
}

int ChannelReceiveData(void *data, int size, int *receiveSize)
{
    return physi_calls.receive_data(data, size, receiveSize);
}

int ChannelSendData(void *data, int size, int *sendSize)
{
    return physi_calls.send_data(data, size, sendSize);
}

EXTERN_C ECode _CPrivateProfile_GetAString(AString fileName, AString appName,
                                  AString keyName, AStringBuf *pReturnedString);

int LowerSwitch(int channel)
{
    switch (channel) {
        case USE_USB:
        //use usb
            physi_calls.port_init = USBInitPort;
            physi_calls.receive_data = USBReceiveData;
            physi_calls.send_data = USBSendData;
            break;
        case USE_SERIAL:
        //use serial
            physi_calls.port_init = SerialInitPort;
            physi_calls.receive_data = SerialReceiveData;
            physi_calls.send_data = SerialSendData;
            break;
        case USE_PIPE:
        default:
        //use pipe
            physi_calls.port_init = PipeInitPort;
            physi_calls.receive_data = PipeReceiveData;
            physi_calls.send_data = PipeSendData;
    }

    return 0;
}

int SwitchPhysicalChannel()
{
    ECode ec;
    AStringBuf_<_MAX_PATH> asFileName;
    AStringBuf_<_MAX_PATH> asAppName;
    AStringBuf_<_MAX_PATH> asKeyName;
    AStringBuf_<_MAX_PATH> asReturnString;

    asFileName.Copy("C:/elastos.cfg");
    asAppName.Copy("CompoundChannel");
    asKeyName.Copy("LowerChannel");

    ec = _CPrivateProfile_GetAString(asFileName, asAppName, asKeyName, &asReturnString);
    if (FAILED(ec)) {
        LowerSwitch(USE_USB);
        return -1;
    }

    if (asReturnString.Compare("Pipe") == 0) {
        LowerSwitch(USE_PIPE);
    }
    else if (asReturnString.Compare("USB") == 0) {
        LowerSwitch(USE_USB);
    }
    else { // "Serial"
        LowerSwitch(USE_SERIAL);
    }

    return 0;
}
